package cn.itsource.user.service.impl;

import cn.itsource.basic.constant.PethomeConstant;
import cn.itsource.basic.constant.VerificationConstant;
import cn.itsource.basic.exception.CustomException;
import cn.itsource.basic.service.impl.BaseServiceImpl;
import cn.itsource.basic.utils.AjaxResult;
import cn.itsource.basic.utils.MD5Utils;
import cn.itsource.basic.utils.StrUtils;
import cn.itsource.user.domain.LoginInfo;
import cn.itsource.user.domain.User;
import cn.itsource.user.domain.dto.LoginInfoDto;
import cn.itsource.user.mapper.LogininfoMapper;
import cn.itsource.user.mapper.UserMapper;
import cn.itsource.user.service.ILogininfoService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class LogininfoServiceImpl extends BaseServiceImpl<LoginInfo> implements ILogininfoService {

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 登录
     * @param loginInfoDto  登录临时对象(username,password,type)
     */
    @Override
    public AjaxResult login(LoginInfoDto loginInfoDto) throws CustomException {
        //校验数据
        checkLoginData(loginInfoDto);
        //根据用户名和type在t_logininfo中查询数据
        LoginInfo loginInfo = logininfoMapper.loadByUsernameAndType(loginInfoDto.getUsername(), loginInfoDto.getType());
        //查询数据为空--》抛出异常：用户名不存在
        if (loginInfo == null) {
            throw new CustomException("用户名不存在!!");
        }
        //检查密码---》密码不相等 抛出异常：密码错误
        if(!loginInfo.getPassword().
                equals(MD5Utils.encrypByMd5(loginInfoDto.getPassword()+loginInfo.getSalt()))){
            throw new CustomException("密码错误!!");
        }

        //随机产生值
        String token = UUID.randomUUID().toString();
        //把登录信息存储到redis里面，并且有效期是30分钟，  key：token   value：登录用户对象
        redisTemplate.opsForValue().set(token, loginInfo, 30, TimeUnit.MINUTES);
        //把token响应到前端服务
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("loginUser", loginInfo);
        return AjaxResult.me().setResultObj(map);
    }


    private void checkLoginData(LoginInfoDto loginInfoDto) throws CustomException {
        if(StringUtils.isEmpty(loginInfoDto.getUsername())){
            throw new CustomException("用户名必填!!");
        }
        if(StringUtils.isEmpty(loginInfoDto.getPassword())){
            throw new CustomException("密码必填!!");
        }
        if(loginInfoDto.getType()==null){
            throw new CustomException("请完善登录信息!!");
        }
    }

    @Override
    public void register(LoginInfoDto loginInfoDto) throws CustomException {
        //校验数据
        checkData(loginInfoDto);
        //创建LoginInfo对象
        LoginInfo loginInfo = createLoginInfo(loginInfoDto);
        logininfoMapper.save(loginInfo);

        //创建User对象
        User user = createUser(loginInfo);
        userMapper.save(user);
    }



    /**
     * 创建User对象
     * @param loginInfo
     * @return
     */
    private User createUser(LoginInfo loginInfo) {
        User user = new User();
        BeanUtils.copyProperties(loginInfo,user);
        //状态  0 待激活  1 正常
        user.setState(PethomeConstant.OK);
        //设置登录信息对象
        user.setLoginInfo(loginInfo);
        return user;
    }

    /**
     * 保存登录信息对象
     * @param loginInfoDto
     * @return
     */
    private LoginInfo createLoginInfo(LoginInfoDto loginInfoDto) {
        LoginInfo loginInfo = new LoginInfo();
        //手机号
        loginInfo.setPhone(loginInfoDto.getPhone());
        //盐值
        loginInfo.setSalt(StrUtils.getComplexRandomString(10));
        //密码
        loginInfo.setPassword(MD5Utils.encrypByMd5(loginInfoDto.getPassword()+loginInfo.getSalt()));
        //0：平台/商家     1：普通用户
        loginInfo.setType(loginInfoDto.getType());
        return loginInfo;
    }

    /**
     * 校验数据
     * @param loginInfoDto  登录信息临时对象
     * @throws CustomException  如果校验失败，抛出此异常
     */
    private void checkData(LoginInfoDto loginInfoDto) throws CustomException {
        //手机号必填
        if(StringUtils.isEmpty(loginInfoDto.getPhone())){
            throw new CustomException("手机号码必填!!");
        }
        //手机号是否已被注册
        User user = userMapper.loadByPhone(loginInfoDto.getPhone());
        if (user != null) {
            throw new CustomException("该手机号码已被注册!!");
        }
        //验证码必填
        if(StringUtils.isEmpty(loginInfoDto.getCode())){
            throw new CustomException("验证码必填!!");
        }
        String codeValue = (String) redisTemplate.opsForValue().get(loginInfoDto.getPhone() + ":" + VerificationConstant.USER_REG);
        //验证码是否过期
        if(StringUtils.isEmpty(codeValue)){
            throw new CustomException("验证码已过期,请重新获取!!");
        }
        //验证码是否正确  78uj:3465763475647456
        if(!loginInfoDto.getCode().toUpperCase().equals(codeValue.split(":")[0].toUpperCase())){
            throw new CustomException("验证码错误!!");
        }
        //密码必填
        if(StringUtils.isEmpty(loginInfoDto.getPassword())){
            throw new CustomException("密码必填!!");
        }
        //重复密码必填
        if(StringUtils.isEmpty(loginInfoDto.getConfigPassword())){
            throw new CustomException("重复密码必填!!");
        }
        //2次密码是否一致
        if(!loginInfoDto.getPassword().equals(loginInfoDto.getConfigPassword())){
            throw new CustomException("2次密码不一致!!");
        }
    }
}
